using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Security;
using System.Collections.Generic;

using Pervote.Core;
using Pervote.Core.Logic;

/// <summary>
/// Summary description for PollService
/// </summary>
[WebService(Namespace = "http://www.pervote.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class PollService : System.Web.Services.WebService
{
    public PollService()
    {
        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    public class WSError
    {
        public long Code;
        public string Description;
    }

    public class WSResult
    {
        public WSError Error = new WSError();

        public void SetError(ErrorInfo error)
        {
            Error.Code = error.ErrorCode;
            Error.Description = error.Message;
        }
    }

    /* Get Votes! */
    public class GetVotesResult : WSResult
    {
        public long TotalVotes;
    }

    public GetVotesResult GetVotes(long itemId)
    {
        GetVotesResult result = new GetVotesResult();
        ErrorInfo error = new ErrorInfo();
        PollItem item = new PollManager().GetPollItem(itemId, error);
        result.SetError(error);
        result.TotalVotes = item.TotalVotes;
        return result;
    }
    /* get votes */

    [WebMethod(EnableSession = true)]
    public WSResult AddComment(long itemId, string text, string link)
    {
        text = HtmlHelper.Sanitize(text);
        link = HtmlHelper.Sanitize(link);
        text = text.Trim();
        link = link.Trim();

        WSResult result = new WSResult();
        MembershipUser user = Membership.GetUser();
        if (user == null)
        {
            result.Error = GetNotLoggedInError();
            return result;
        }
        if (string.IsNullOrEmpty(text) && string.IsNullOrEmpty(link))
        {
            result.Error.Code = -1;
            result.Error.Description = "The comment is empty.";
            return result;
        }

        PollItemComment comment = new PollItemComment();
        comment.AddedBy = user.UserName;
        comment.Text = text;
        comment.Link = link;
        ErrorInfo error = new ErrorInfo();
        new PollManager().AddItemComment(itemId, comment, error);
        result.SetError(error);
        return result;
    }

    /* Get Votes! */
    public class VoteResult : WSResult
    {
        public long TotalVotes;
        public bool CanVoteAgain;
    }

    [WebMethod(EnableSession = true)]
    public VoteResult Vote(long itemId)
    {
        long totalVotes = 0; //init
        bool canVoteAgain = false; //init
        VoteResult result = new VoteResult();
        MembershipUser user = Membership.GetUser();
        if (user == null)
        {
            result.Error = GetNotLoggedInError();
            return result;
        }
        ErrorInfo error = new ErrorInfo();
        new PollManager().Vote(itemId, user.UserName, ref totalVotes, ref canVoteAgain, error);
        result.SetError(error);
        result.CanVoteAgain = canVoteAgain;
        result.TotalVotes = totalVotes;
        return result;
    }

    [WebMethod(EnableSession = true)]
    public WSResult AddItem(long pollId, string itemName, string commentText, string link)
    {
        itemName = HtmlHelper.Sanitize(itemName);
        commentText = HtmlHelper.Sanitize(commentText, 8000); //8000 is our max-length
        link = HtmlHelper.Sanitize(link);

        WSResult result = new WSResult(); MembershipUser user = Membership.GetUser();
        if (user == null)
        {
            result.Error = GetNotLoggedInError();
            return result;
        }
        if (String.IsNullOrEmpty(itemName))
        {
            result.Error.Code = -1;
            result.Error.Description = "The item name is empty.";
            return result;
        }

        result.Error.Code = -1;
        ErrorInfo error = new ErrorInfo();            
        try
        {
            PollManager pm = new PollManager();
            PollItem pi = new PollItem();
            pi.Name = itemName;
            pi.PollId = pollId;
            pi.AddedBy = user.UserName;
            pi.Id = pm.AddItem(pi, error);

            if (pi.Id > 0 && (commentText != "" || link != ""))
            {
                PollItemComment ic = new PollItemComment();
                ic.AddedBy = user.UserName;
                ic.Text = commentText;
                ic.Link = link;
                pm.AddItemComment(pi.Id, ic, error);
            }
            result.Error.Code = 0;
        }
        catch //if something bombs we will get the error code.
        {
            throw;
        }   
        return result;
    }

    /* Is Logged In? */
    public class IsLoggedInResult : WSResult
    {
        public bool IsLoggedIn = false;
    }

    [WebMethod(EnableSession = true)]
    public IsLoggedInResult IsLoggedIn()
    {
        IsLoggedInResult result = new IsLoggedInResult();
        MembershipUser user = Membership.GetUser();
        if (user == null) result.IsLoggedIn = false;
        else result.IsLoggedIn = true;
        return result;
    }
    /* is logged in! */
    
    /* GetCommentsResult */

    public class GetCommentsResultEntry
    {
        public long Id;
        public string Text;
        public string Link;
        public string AddedBy;
        public bool UserRated;
    }

    public class GetCommentsResult : WSResult
    {
        public List<GetCommentsResultEntry> Comments = new List<GetCommentsResultEntry>();
    }

    [WebMethod]
    public GetCommentsResult GetComments(long itemId, int startRank, int numComments)
    {
        GetCommentsResultEntry entry;
        GetCommentsResult result = new GetCommentsResult();
        MembershipUser user = Membership.GetUser();
        string userName = (user == null) ? null : user.UserName;

        PollManager manager = new PollManager();
        ErrorInfo error = new ErrorInfo();
        List<PollItemComment> comments = manager.GetItemComments(itemId, userName, startRank, numComments, error);
        result.SetError(error);
        foreach (PollItemComment comment in comments)
        {
            entry = new GetCommentsResultEntry();
            entry.Id = comment.Id;
            entry.Text = comment.Text;
            entry.Link = comment.Link + "";
            entry.AddedBy = comment.AddedBy;
            entry.UserRated = comment.UserRated;
            result.Comments.Add(entry);
        }
        return result;
    }
    /* --- GetCommentsResult --- */

    //Returns TRUE if the user is not logged in
    private WSError GetNotLoggedInError()
    {
        WSError error = new WSError();
        error.Code = (int)PollManager.VotingErrors.UserNameIsNull;
        error.Description = "Please login to continue.";
        return error;
    }

    [WebMethod(EnableSession = true)]
    public WSResult LogPollIssue(long pollId, string issueType, string description)
    {
        issueType = HtmlHelper.Sanitize(issueType);
        description = HtmlHelper.Sanitize(description);

        WSResult result = new WSResult();
        MembershipUser user = Membership.GetUser();
        string userName = (user == null) ? null : user.UserName;

        ErrorInfo error = new ErrorInfo();
        new PollManager().LogPollIssue(pollId, issueType, description, userName, error);
        result.SetError(error);
        return result;
    }

    [WebMethod(EnableSession = true)]
    public WSResult RateComment(long commentId, int rating)
    {
        WSResult result = new WSResult();
        MembershipUser user = Membership.GetUser();
        ErrorInfo error = new ErrorInfo();
        if (user == null)
        {
            error.ErrorCode = -1;
            error.Message = "User is needs to login to rate a comment.";
        }
        else
        {
            new PollManager().RateComment(commentId, rating, user.UserName, error);
        }
        result.SetError(error);
        return result;
    }
}